This repository has no description
1import { createHmac } from "node:crypto";
2import { error } from "@sveltejs/kit";
3import { getConfig } from "$lib/server/config";
4import type { RequestHandler } from "./$types";
5
6// the signed url only changes when the secret does, so it can cache for a day
7const MAX_AGE = 86400;
8
9const HEX = /^(?:[0-9a-f]{2})+$/;
10
11export const GET: RequestHandler = ({ params }) => {
12 const hex = params.hex.toLowerCase();
13 if (!HEX.test(hex)) error(400, "Not a camo url");
14
15 const target = Buffer.from(hex, "hex").toString("utf8");
16 let parsed: URL;
17 try {
18 parsed = new URL(target);
19 } catch {
20 error(400, "Not a camo url");
21 }
22 if (parsed.protocol !== "http:" && parsed.protocol !== "https:") {
23 error(400, "Not a camo url");
24 }
25
26 // redirecting unsigned would make this an open redirect, so no secret means
27 // no images at all
28 const { camoUrl, camoSecret } = getConfig();
29 if (!camoSecret) error(404, "Camo is not configured");
30
31 const signature = createHmac("sha256", camoSecret).update(target).digest("hex");
32 return new Response(null, {
33 status: 302,
34 headers: {
35 location: `${camoUrl}/${signature}/${hex}`,
36 "cache-control": `public, max-age=${MAX_AGE}`
37 }
38 });
39};